package org.piax.dtpubsub;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.piax.gnt.ReceiveListener;
import org.piax.gnt.Target;
import org.piax.ov.jmes.Message;
import org.piax.ov.jmes.MessageData;
import org.piax.ov.ovs.dtn.DTN;
import org.piax.ov.ovs.dtn.ebc.EpidemicBroadcast;
import org.piax.ov.ovs.dtn.impl.AndroidDTN;
import org.piax.trans.common.PeerId;
import org.piax.trans.util.Base64;

import android.content.Context;
import android.os.Build;

public class DTPubSub implements ReceiveListener {
	DTN dtn;
	List<Subscription> subscriptions;
	
	class Subscription {
		public String topic;
		public SubscribeListener listener;
		public Subscription(String topic, SubscribeListener listener) {
			this.topic = topic;
			this.listener = listener;
		}
	}

	public DTPubSub(Context ctxt) {
		subscriptions = new ArrayList<Subscription>();
		Map<Integer, Object> params = new HashMap<Integer, Object>();
		
		params.put(AndroidDTN.ANDROID_CONTEXT, ctxt);
        params.put(AndroidDTN.PEER_NAME, Build.MODEL);
        params.put(AndroidDTN.PEER_ID, PeerId.newId());
        params.put(AndroidDTN.ALGORITHM, new EpidemicBroadcast());
        params.put(AndroidDTN.TSD_ENABLE_BLUETOOTH, true); 
        params.put(AndroidDTN.USE_BLUETOOTH, true); 
        params.put(AndroidDTN.TSD_TIMEOUT_PERIOD, 5);
        dtn = AndroidDTN.getInstance("AndroidDTN", params);
        dtn.start();
        dtn.clearReceiveListeners();
        dtn.addReceiveListener(this);
	}
	
	public void finish() {
		dtn.stop();
		dtn = null;
	}

	@Override
	public void onReceive(Target target, Serializable payload) {
		Message m = (Message) payload;
    	MessageData message = m.data;
    	byte[] data = null;
		try {
			data = Base64.decode(message.text);
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (data != null) {
			for (Subscription sub : subscriptions) {
				if (sub.topic.equals(message.condition)) {
					sub.listener.onReceive(sub.topic, data);
				}
			}
		}
	}
	
	public void subscribe(String topic, SubscribeListener listener) {
		subscriptions.add(new Subscription(topic, listener));
	}
	
	public void unsubscribe(SubscribeListener listener) {
		subscriptions.remove(listener);
	}
	
	public void publish(String topic, byte[] data) {
		MessageData md = new MessageData(Base64.encodeBytes(data));
		md.condition = topic;
		dtn.newMessage(md);
	}
	
}
